package main

import (
	_ "embed"
	"flag"
	"fmt"
	"os"
	"regexp"
	"strings"
)

var libname = flag.String("name", "lib", "namespace")
var input = flag.String("input", "lib.h", "input")
var output = flag.String("output", "lib.d.ts", "output")
var extraContent = `
	function malloc($0 : number): number;
	function free($0 : number): void;
	function calloc($0 : number, $1 : number): number;
	function realloc($0 : number, $1 : number): number;
	function _start(): void;
	function resume(): void;
	function go_scheduler(): void;
`

func main() {
	flag.Parse()
	dtsfile := *input
	content, err := os.ReadFile(dtsfile)
	if err != nil {
		panic(err)
	}
	os.RemoveAll(dtsfile)
	exp, err := regexp.Compile(fmt.Sprintf(`(.*)w2c_(.*)%s_(.*)\((.*)\);`, *libname))
	if err != nil {
		panic(exp)
	}
	gp := exp.FindAllStringSubmatch(string(content), -1)
	builder := new(strings.Builder)
	builder.WriteString(fmt.Sprintf("declare namespace %s{\n", *libname))
	builder.WriteString("\tconst memory: WebAssembly.Memory;")
	builder.WriteString(fmt.Sprintf("%s", extraContent))
	for _, p := range gp {
		ret := strings.TrimSpace(p[1])
		fname := fmt.Sprintf("%s_%s", *libname, p[3])
		args := strings.TrimSpace(p[4])
		ss := strings.Split(args, ",")
		bd := new(strings.Builder)
		for i, s := range ss {
			if i == 0 {
				continue
			}
			bd.WriteString(fmt.Sprintf("arg%d:%s", i, s))
			bd.WriteString(",")
		}
		args = bd.String()
		args = strings.TrimSuffix(args, ",")
		sprintf := fmt.Sprintf("\tfunction %s(%s):%s;\n", fname, args, ret)
		sprintf = strings.ReplaceAll(sprintf, "u32", "number")
		sprintf = strings.ReplaceAll(sprintf, "u64", "number")
		sprintf = strings.ReplaceAll(sprintf, "f32", "number")
		sprintf = strings.ReplaceAll(sprintf, "f64", "number")
		builder.WriteString(sprintf)
	}
	builder.WriteString("}\n")
	err = os.WriteFile(*output, []byte(builder.String()), os.ModePerm)
	if err != nil {
		panic(err)
	}
}
